package cn.com.demo.cms;

import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.cms.SignerInformation;
import org.bouncycastle.cms.SignerInformationStore;

import java.security.cert.*;
import java.util.Collections;
import java.util.Iterator;


public class SignedDataProcessor {


    /**
     * Build a path using the given root as the trust anchor, and the passed
     * in end constraints and certificate store.
     * <p>
     * Note: the path is built with revocation checking turned off.
     */
    public static PKIXCertPathBuilderResult buildPath(X509Certificate rootCert,
                                                      X509CertSelector endCertSelector,
                                                      CertStore certsAndCrls
    ) throws Exception {
        CertPathBuilder builder = CertPathBuilder.getInstance("PKIX", "BC");
        PKIXBuilderParameters params = new PKIXBuilderParameters
                (Collections.singleton(new TrustAnchor(rootCert, null)),
                        endCertSelector);
        params.addCertStore(certsAndCrls);
        params.setRevocationEnabled(false);

        return (PKIXCertPathBuilderResult) builder.build(params);
    }

    /**
     * Return a boolean array representing keyUsage with digitalSignature set.
     */
    static boolean[] getKeyUsageForSignature() {
        boolean[] val = new boolean[9];
        val[0] = true;
        return val;
    }

    @SuppressWarnings("deprecation")
    public static boolean isValid(
            CMSSignedData signedData, X509Certificate rootCert) throws Exception {
        CertStore certsAndCrls = signedData.getCertificatesAndCRLs("Collection", "BC");
        SignerInformationStore signers = signedData.getSignerInfos();
        Iterator i = signers.getSigners().iterator();
        if (i.hasNext()) {
            SignerInformation signInfo = (SignerInformation) i.next();
            X509CertSelector signerSelector = signInfo.getSID();
            signerSelector.setKeyUsage(getKeyUsageForSignature());
            PKIXCertPathBuilderResult result = buildPath(rootCert, signerSelector, certsAndCrls);
            return signInfo.verify(result.getPublicKey(), "BC");
        }
        return false;
    }
}
